package com.shenmazong.serverwebpoem.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.google.code.kaptcha.Constants;
import com.shenmazong.serverwebpoem.pojo.*;
import com.shenmazong.serverwebpoem.service.TbCollectionService;
import com.shenmazong.serverwebpoem.service.TbPoetryInfoService;
import com.shenmazong.serverwebpoem.service.TbUserService;
import com.shenmazong.serverwebpoem.util.IpUtil;
import com.shenmazong.serverwebpoem.util.ParamUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author 田不平
 * @project server-web-poem
 * @date 2020/4/1 11:00 AM
 * http://www.shenmazong.com
 */

@Slf4j
@Controller
@RequestMapping(value = "/")
public class UserController {

    @Autowired
    TbUserService tbUserService;

    @Autowired
    TbCollectionService tbCollectionService;

    @Autowired
    TbPoetryInfoService tbPoetryInfoService;

    /**
     * TODO 显示登录页面
     * @return
     */
    @RequestMapping(value = "/login")
    public String login() {
        return "login";
    }

    /**
     * TODO 执行登录
     * @param request
     * @param model
     * @return
     */
    @PostMapping(value = "/doLogin")
    public String doLogin(HttpServletRequest request, Model model) {
        log.info("login,...");

        String userName = request.getParameter("username");
        String userPass = request.getParameter("password");
        String verifyCode = request.getParameter("verifycode");

        //-- 检查验证码
        if(verifyCode == null || verifyCode.length() == 0) {
            log.info("login, 验证码错误...");
            model.addAttribute("msg", "验证码错误");
            return "login";
        }
        String realCode = (String) request.getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY);
        if(!realCode.equals(verifyCode)) {
            log.info("login, 验证码错误...");
            model.addAttribute("msg", "验证码错误");
            return "login";
        }

        //-- 登录验证
        if(userName == null || userName.length() == 0) {
            log.info("login, 没有登录账号...");
            model.addAttribute("msg", "用户名不存在");
            return "login";
        }
        if(userPass == null || userPass.length() == 0) {
            log.info("login, 没有登录密码...");
            model.addAttribute("msg", "密码错误");
            return "login";
        }

        //--1 获取Subject
        Subject subject = SecurityUtils.getSubject();

        //--2 封装用户
        UsernamePasswordToken token = new UsernamePasswordToken(userName, userPass);

        //--3 执行登录
        try {
            subject.login(token);

            // 登录成功，记录登录信息
            TbUser user = (TbUser) subject.getPrincipal();
            String ip = IpUtil.getIpAddr(request);
            user.setLoginip(ip);

            Date date = new Date();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            user.setLasttime(sdf.format(date));

            user.setLogintimes(user.getLogintimes()+1);
            tbUserService.set(user);

            // 当天第一次登录，赠送积分
            SimpleDateFormat sdfRecord = new SimpleDateFormat("yyyyMMdd");
            TbRecordLogin recordLogin = tbUserService.getUserRecordByDate(user.getId(), Integer.parseInt(sdfRecord.format(date)));
            if(recordLogin == null) {
                tbUserService.addRecordStoneById(user, 100L, "登录送积分");
            }

            // 添加登录记录
            TbRecordLogin newRecordLogin = new TbRecordLogin();
            newRecordLogin.setUserid(user.getId());
            newRecordLogin.setNickname(user.getNickname());
            newRecordLogin.setLoginip(ip);

            newRecordLogin.setLogindate(Integer.parseInt(sdfRecord.format(date)));
            tbUserService.addRecordLogin(newRecordLogin);

            // 跳转到 index.html
            return "redirect:/index";
        }
        catch (UnknownAccountException e) {
            log.info("login,用户名不存在");
            model.addAttribute("msg", "用户名不存在");
            return "login";
        }
        catch (IncorrectCredentialsException e) {
            log.info("login,密码错误");
            model.addAttribute("msg", "密码错误");
            return "login";
        }
        catch (AuthenticationException e) {
            log.info("login,未知错误");
            model.addAttribute("msg", "未知错误");
            return "login";
        }
    }

    /**
     * TODO 执行退出操作
     * @return
     */
    @GetMapping(value = "/logout")
    public String logout() {

        Subject subject = SecurityUtils.getSubject();
        subject.logout();

        return "login";
    }

    /**
     * TODO 注册
     * @return
     */
    @RequestMapping(value = "/signup")
    public String signup(HttpServletRequest request, Model model) {
        log.info("signup,...");

        // 接收参数
        String userName = request.getParameter("username");
        String userPass = request.getParameter("password");

        if(userName == null || userName.length() == 0) {
            log.info("signup, 没有登录账号...");
            model.addAttribute("msg", "没有登录账号");
            return "signup";
        }
        if(userPass == null || userPass.length() == 0) {
            log.info("signup, 没有登录密码...");
            model.addAttribute("msg", "没有登录密码");
            return "signup";
        }

        // 检查用户名
        TbUser user = tbUserService.getUserByName(userName);
        if(user != null) {
            log.info("signup, 用户名已被占用...");
            model.addAttribute("msg", "用户名已被占用");
            return "signup";
        }

        // 增加用户
        user = new TbUser();
        user.setUsername(userName);

        String hashPass = DigestUtils.md5DigestAsHex(userPass.getBytes());
        user.setUserpass(hashPass);

        user.setNickname("博雅诗友");

        String ip = IpUtil.getIpAddr(request);
        user.setLoginip(ip);
        user.setRegip(ip);

        user.setLogintimes(1);

        tbUserService.add(user);
        if(user.getId() <= 0) {
            log.info("signup, 注册失败...");
            model.addAttribute("msg", "未知原因注册失败");
            return "signup";
        }

        //-- 增加用户积分
        user = tbUserService.getUserById(user.getId());
        tbUserService.addRecordStoneById(user, 100L, "注册送积分");

        // 跳转登录
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(userName, userPass);

        try {
            subject.login(token);
        }
        catch (Exception e) {
            model.addAttribute("msg", "未知原因跳转失败，请重新登录。");
            return "login";
        }

        return "redirect:/index";
    }

    /**
     * TODO 增加收藏记录接口
     * @param request
     * @return
     */
    @PostMapping(value = "/doCollect")
    @ResponseBody
    public Object doCollect(HttpServletRequest request) {
        Map<String,Object> resultMap = new HashMap<>();

        //-- 检查参数
        Integer poetryId = ParamUtils.getIntParameter(request, "poetryId", 0);
        Integer userId = ParamUtils.getIntParameter(request, "userId", 0);
        String title = ParamUtils.getParameter(request, "title", "");
        if(poetryId <= 0 || userId <= 0) {
            resultMap.put("result", -1);
            resultMap.put("msg", "参数违法");
            return resultMap;
        }

        //--1 检查是否已经添加收藏
        TbCollection collection = tbCollectionService.getByAuthorAndPoetry(userId, poetryId);
        if(collection != null) {
            resultMap.put("result", -1);
            resultMap.put("msg", "已经收藏了");
            return resultMap;
        }

        //--2 添加收藏
        collection = new TbCollection();
        collection.setUserid(userId);
        collection.setPoetryid(poetryId);
        collection.setTitle(title);
        tbCollectionService.add(collection);

        //--3 增加收藏计数
        TbPoetryInfo info = tbPoetryInfoService.getByPoetryId(poetryId);
        if(info != null) {
            info.setCollections(info.getCollections()+1);
            tbPoetryInfoService.set(info);
        }
        else {
            info = new TbPoetryInfo();

            info.setCollections(1);
            info.setPoetryid(poetryId);
            tbPoetryInfoService.add(info);
        }

        resultMap.put("result", 0);
        resultMap.put("collections", info.getCollections());
        return resultMap;
    }

    /**
     * TODO 收藏页面展示
     * @param model
     * @param pageNo
     * @return
     */
    @GetMapping(value = "/collection/{pageNo}")
    public String collection(Model model, @PathVariable(name = "pageNo") Integer pageNo) {

        //-- 获取登录用户信息
        Subject subject = SecurityUtils.getSubject();
        TbUser user = (TbUser)subject.getPrincipal();
        if(user == null) {
            return "redirect:/login";
        }
        model.addAttribute("user", user);

        IPage<TbCollection> iPage = tbCollectionService.getMapCollectionByPage(user.getId(), pageNo, 10);
        List<TbCollection> collections = iPage.getRecords();
        log.info("collections={}", collections.size());

        model.addAttribute("collections", collections);
        model.addAttribute("pageCurrent", pageNo);
        model.addAttribute("pageSize", 10);
        model.addAttribute("pageCount", iPage.getPages());
        model.addAttribute("count", iPage.getTotal());

        //-- 添加分页信息
        if(pageNo < 5) {
            List<Integer> pages = new ArrayList<>();
            for(Integer idx=1; idx<8; idx++) {
                if(idx>iPage.getPages())
                    break;
                pages.add(idx);
            }
            model.addAttribute("pages", pages);
        }
        else {
            List<Integer> pages = new ArrayList<>();
            for(Integer idx=pageNo-3; idx<pageNo+4; idx++) {
                if(idx>iPage.getPages())
                    break;
                pages.add(idx);
            }
            model.addAttribute("pages", pages);
        }

        return "collection";
    }

    /**
     * TODO 展示用户积分记录
     * @param model
     * @param pageNo
     * @return
     */
    @GetMapping(value = "/stone/{pageNo}")
    public String stone(Model model, @PathVariable(name = "pageNo") Integer pageNo) {

        //-- 获取登录用户信息
        Subject subject = SecurityUtils.getSubject();
        TbUser user = (TbUser)subject.getPrincipal();
        if(user == null) {
            return "redirect:/login";
        }
        model.addAttribute("user", user);

        IPage<TbRecordStone> iPage = tbUserService.getPageStoneByUserId(user.getId(), pageNo, 10);
        List<TbRecordStone> stones = iPage.getRecords();
        log.info("stones={}", stones.size());

        model.addAttribute("stones", stones);
        model.addAttribute("pageCurrent", pageNo);
        model.addAttribute("pageSize", 10);
        model.addAttribute("pageCount", iPage.getPages());
        model.addAttribute("count", iPage.getTotal());

        //-- 添加分页信息
        if(pageNo < 5) {
            List<Integer> pages = new ArrayList<>();
            for(Integer idx=1; idx<8; idx++) {
                if(idx>iPage.getPages())
                    break;
                pages.add(idx);
            }
            model.addAttribute("pages", pages);
        }
        else {
            List<Integer> pages = new ArrayList<>();
            for(Integer idx=pageNo-3; idx<pageNo+4; idx++) {
                if(idx>iPage.getPages())
                    break;
                pages.add(idx);
            }
            model.addAttribute("pages", pages);
        }

        return "stone";
    }
}
